<?php

namespace common\service;

use common\exception\LogicException;
use common\model\TaskModel;
use support\ErrorCode;
use support\SingletonTrait;

class TaskLockService
{

    // 单例工具
    use SingletonTrait;

    /**
     * 检测是否能锁定任务
     * @param $taskId
     * @param $data
     * @return void
     * @throws \think\Exception
     */
    public function checkLockTask($taskId, $data)
    {

        if (!isset($data['is_lock'])) {
            return;
        }

        $param = [
            'filter' => ['task.id' => $taskId],
            'fields' => "name,plan_delivery_time,plan_end_time,is_lock"
        ];
        $commonService = CommonService::instance("task");
        $taskList = $commonService->select($param, "task")['rows'] ?? [];
        $newLock = $data['is_lock'] == 'yes';
        if ($newLock) { // 加锁
            foreach ($taskList as $taskItem) {
                $isLock = isset($taskItem['task']['is_lock']) && $taskItem['task']['is_lock'] == 'yes';
                $taskName = $taskItem['task']['name'];
                //1、已锁定任务不能重复锁定
                if ($isLock) {
                    throw new LogicException($taskName . " task can't repeat lock", ErrorCode::TASK_ALREADY_LOCK);
                }

                //2、无计划交付时间不能锁定
                if (empty($taskItem['task']['plan_delivery_time'])) {
                    throw new LogicException($taskName . " task not set plan delivery time", ErrorCode::TASK_NO_PLAN_DELIVERY_TIME_LOCK);
                }

                //3、未设定计划完成时间不能锁定
                if (empty($taskItem['task']['plan_end_time'])) {
                    throw new LogicException($taskName . " task not set plan end time", ErrorCode::TASK_NO_PLAN_END_TIME_LOCK);
                }
            }
        } else {
            foreach ($taskList as $taskItem) {
                $noLock = !isset($taskItem['task']['is_lock']) || $taskItem['task']['is_lock'] == 'no';
                $taskName = $taskItem['task']['name'];
                //未锁定的任务不能解锁
                if ($noLock) {
                    throw new LogicException($taskName . " task no lock", ErrorCode::TASK_NO_LOCK);
                }
            }
        }
    }

    /**
     * 给任务加锁
     * @param $taskIds
     * @param $isLock
     * @return int
     * @throws \think\Exception
     */
    public function switchTaskLock($taskIds, $isLock)
    {
        //检测是否能锁定
        $this->checkLockTask(["IN", $taskIds], ['is_lock' => $isLock]);
        return CommonService::instance("task")->commonBatchUpdateSame(['id' => $taskIds, 'is_lock' => $isLock], module_by_code("task"));
    }

    /**
     * 任务锁定时检测更新
     * @param $isLock
     * @param $newData
     * @return void
     */
    public function taskLockedCheckUpdate($isLock, $newData)
    {
        //未锁定不检测
        if (!$isLock) {
            return;
        }
        //不能修改计划开始时间和计划结束时间
        if (isset($newData['plan_end_time']) || isset($newData['plan_start_time'])) {
            throw  new LogicException("task already lock", ErrorCode::TASK_ALREADY_LOCK);
        }
    }

    /**
     * 任务锁定时检测更新的数据
     * @param $taskId
     * @param $newData
     * @return void
     * @throws \think\Exception
     */
    public function TaskLockedCheckUpdateData($taskId, $newData)
    {
        if (isset($newData['is_lock'])) {
            $this->checkLockTask(["IN" => $taskId], $newData);
        } else {
            $commonService = CommonService::instance("task");
            $commonService->setCurrentModuleCode("task");
            $task = $commonService->find(['filter' => ['id' => $taskId]]);
            $this->taskLockedCheckUpdate(isset($task['is_lock']) && $task['is_lock'] == 'yes', $newData);
        }
    }
}